package com.ebuildy.component
{
	import flash.display.DisplayObject;
	import flash.utils.Dictionary;
	import flash.utils.setTimeout;
	
	import mx.collections.ArrayCollection;
	import mx.core.ClassFactory;
	import mx.core.Container;
	import mx.core.IDataRenderer;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	import mx.events.PropertyChangeEvent;
	
	public class RepeaterManager
	{
		static private var listInstances:Dictionary = new Dictionary(true);
		
		static public function newRepeater(target:Container, itemRenderer:Class, data:ArrayCollection,max:Number = 10000):RepeaterManager
		{
			var instance:RepeaterManager = new RepeaterManager(target,itemRenderer,data,max);
			
			listInstances[target] = instance;
			
			return instance;
		}
		
		public var target:Container;
		public var itemRenderer:ClassFactory;
		public var max:Number;
		public var data:ArrayCollection;
		
		public function RepeaterManager(target:Container, itemRenderer:Class, data:ArrayCollection,max:Number)
		{
			this.max = max;
			this.target = target;
			this.itemRenderer = new ClassFactory(itemRenderer);
			this.data = data;
			
			data.addEventListener(CollectionEvent.COLLECTION_CHANGE, onCollectionChange,false, 0, false);
			
			refresh();
		}
		
		public function addFromArray(data:Array):void
		{
			for each (var item:Object in data)
			{
				if (this.target.numChildren >= this.max)
				{
					return ;
				}				
				
				add(item);
			}
		}
		
		public function clear():void
		{
			this.target.removeAllChildren();
		}
		
		public function refresh():void
		{
			for each (var item:Object in this.data)
			{
				if (getRendererFromData(item))
				{
					getRendererFromData(item).data = item;	
				}
				else if (this.target.numChildren < this.max)
				{
					add(item);
				}		
			}
		}
		
		public function getRendererFromData(item:Object):IDataRenderer
		{
			for each (var child:IDataRenderer in this.target.getChildren())
			{
				if (child.data == item)
				{
					return child;
				}
			}
			
			return null;
		}
		
		static private var counter:int = 0;
		
		public function add(item:Object):void
		{
			setTimeout(addDefferred,counter*100,item);
			counter ++;
		}
		
		private function addDefferred(item:Object):void
		{
			if (this.getRendererFromData(item) == null)
			{
				var instance:DisplayObject = this.itemRenderer.newInstance() as DisplayObject;
				
				IDataRenderer(instance).data = item; 
					
				this.target.addChild(instance);
				
				if (counter > 0)
				{
					counter --;
				}
			}
		}
		
		private function onCollectionChange(e:CollectionEvent):void
		{
			if (e.kind == CollectionEventKind.RESET)
			{
				clear();
			}
			else
			{
				for each (var item:Object in e.items)
				{
					if (e.kind == CollectionEventKind.ADD)
					{
						if (this.target.numChildren >= this.max)
						{
							return ;
						}						
						
						add(item);				
					}
					else if (e.kind == CollectionEventKind.REMOVE)
					{
						for each (var child:IDataRenderer in this.target.getChildren())
						{
							if (child.data == item)
							{
								this.target.removeChild(child as DisplayObject);
									
								break;
							}
						}
					}
					else if (e.kind == CollectionEventKind.UPDATE)
					{
						for each (child in this.target.getChildren())
						{
							if (child.data == PropertyChangeEvent(item).source)
							{
								child.data = PropertyChangeEvent(item).source;
									
								break;
							}
						}
					}
				}
			}
		}

	}
}